package nl.harmidi.harmonictable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nl.harmidi.midi.MidiTranslator;

import org.grlea.log.SimpleLogger;

public class TableModel {
	private static final SimpleLogger log = new SimpleLogger(TableModel.class);

	private List<Spot> allSpots = new ArrayList<Spot>();

	private Map<Integer, List<Spot>> spotRows;

	private Map<Integer, String[]> stringRows;

	public TableModel() {
		log.entry("TableModel()");
		createStringRows();
		createSpotRows();
		log.exit("TableModel()");
	}

	private void createStringRows() {
		stringRows = new HashMap<Integer, String[]>();
		int row = 1;
		stringRows.put(row++, new String[] { "C 7", null, null, null, null, null, null, null });
		stringRows.put(row++, new String[] { "G#6", "A 6", "A#6", "B 6", "C 7", null, null, null, null });
		stringRows.put(row++, new String[] { "F 6", "F#6", "G 6", "G#6", "A 6", "A#6", "B 6", "C 7" });
		stringRows.put(row++, new String[] { "C#6", "D 6", "D#6", "E 6", "F 6", "F#6", "G 6", "G#6", "A 6" });
		stringRows.put(row++, new String[] { "A#5", "B 5", "C 6", "C#6", "D 6", "D#6", "E 6", "F 6" });
		stringRows.put(row++, new String[] { "F#5", "G 5", "G#5", "A 5", "A#5", "B 5", "C 6", "C#6", "D 6" });
		stringRows.put(row++, new String[] { "D#5", "E 5", "F 5", "F#5", "G 5", "G#5", "A 5", "A#5" });
		stringRows.put(row++, new String[] { "B 4", "C 5", "C#5", "D 5", "D#5", "E 5", "F 5", "f#5", "G 5" });
		stringRows.put(row++, new String[] { "G#4", "A 4", "A#4", "B 4", "C 5", "C#5", "D 5", "D#5" });
		stringRows.put(row++, new String[] { "E 4", "F 4", "F#4", "G 4", "G#4", "A 4", "A#4", "B 4", "C 5" });
		stringRows.put(row++, new String[] { "C#4", "D 4", "D#4", "E 4", "F 4", "F#4", "G 4", "G#4" });
		stringRows.put(row++, new String[] { "A 3", "A#3", "B 3", "C 4", "C#4", "D 4", "D#4", "E 4", "F 4" });
		stringRows.put(row++, new String[] { "F#3", "G 3", "G#3", "A 3", "A#3", "B 3", "C 4", "C#4" });
		stringRows.put(row++, new String[] { "D 3", "D#3", "E 3", "F 3", "F#3", "G 3", "G#3", "A 3", "A#3" });
		stringRows.put(row++, new String[] { "B 2", "C 3", "C#3", "D 3", "D#3", "E 3", "F 3", "F#3" });
		stringRows.put(row++, new String[] { "G 2", "G#2", "A 2", "A#2", "B 2", "C 3", "C#3", "D 3", "D#3" });
		stringRows.put(row++, new String[] { "E 2", "F 2", "F#2", "G 2", "G#2", "A 2", "A#2", "B 2" });
		stringRows.put(row++, new String[] { "C 2", "C#2", "D 2", "D#2", "E 2", "F 2", "F#2", "G 2", "G#2" });
		stringRows.put(row++, new String[] { "A 1", "A#1", "B 1", "C 2", "C#2", "D 2", "D#2", "E 2" });
		stringRows.put(row++, new String[] { null, null, null, null, "A 1", "A#1", "B 1", "C 2", "C#2" });
		stringRows.put(row++, new String[] { null, null, null, null, null, null, null, "A 1" });
	}

	private void createSpotRows() {
		spotRows = new HashMap<Integer, List<Spot>>();
		for (int rowNr = 1; rowNr <= 21; rowNr++) {
			List<Spot> spotRow = new ArrayList<Spot>();
			int column = 1;
			for (String noteString : stringRows.get(rowNr)) {
				spotRow.add(getSpotFor(rowNr, column++, noteString));
			}
		}
	}

	private Spot getSpotFor(int row, int column, String noteString) {
		Spot spot;
		if (noteString != null) {
			spot = new Spot(row, column, MidiTranslator.getNoteNumber(noteString));
		} else {
			spot = new EmptySpot(row, column);
		}
		allSpots.add(spot);
		log.debugObject("TableModel: new Spot created: ", spot);
		return spot;
	}

	public List<Spot> getAllSpots() {
		return allSpots;
	}

	public void setAllSpots(List<Spot> allSpots) {
		this.allSpots = allSpots;
	}

	public Map<Integer, List<Spot>> getSpotRows() {
		return spotRows;
	}

	public void setSpotRows(Map<Integer, List<Spot>> spotRows) {
		this.spotRows = spotRows;
	}

	/**
	 * Resets all spots to be off
	 */
	public void reset() {
		for (Spot spot : getAllSpots()) {
			if (!(spot instanceof EmptySpot)) {
				spot.reset();
			}
		}
	}

}
